package com.llk.MyThread;//参考：https://blog.csdn.net/m0_61840987/article/details/146041997

import java.util.LinkedList;
import java.util.Queue;

/**
 * src.main.java.com.jvonneumann.MyThread.BlockingQueue 类实现了一个简单的阻塞队列。
 * 该队列采用内部锁和 wait/notifyAll 机制，
 * 保证在队列为空时调用 take() 方法的线程会阻塞，
 * 在队列满时调用 put() 方法的线程也会阻塞，直到有空间。
 *
 * @param <T> 队列中存储的数据类型
 */
public class BlockingQueue<T> {
    // 内部队列，使用 LinkedList 存储数据
    private final Queue<T> queue = new LinkedList<>();
    // 队列的最大容量
    private final int capacity;

    /**
     * 构造方法，根据指定容量初始化队列。
     *
     * @param capacity 队列的最大容量
     * @throws IllegalArgumentException 如果容量小于等于 0
     */
    public BlockingQueue(int capacity) {
        if (capacity <= 0) {
            throw new IllegalArgumentException("容量必须大于 0");
        }
        this.capacity = capacity;
    }

    /**
     * put 方法用于向队列中添加数据。
     * 如果队列已满，则当前线程会被阻塞，直到有空间。
     * 由于LinkedList不是线程安全的类，要加锁，并发安全问题看源码可以分析出来。同时，因为要使用wait和notyfiall，需要结合synchronized使用
     *
     * @param item 要添加的数据
     * @throws InterruptedException 如果线程等待期间被中断
     */
    public synchronized void put(T item) throws InterruptedException {
        while (queue.size() == capacity) {
            // 队列已满，等待空位出现
            wait();
        }
        queue.offer(item);
        // 添加元素后唤醒等待的线程
        notifyAll();
    }

    /**
     * take 方法用于从队列中获取数据。
     * 如果队列为空，则当前线程会被阻塞，直到有数据可取。
     *
     * @return 队列头部的数据
     * @throws InterruptedException 如果线程等待期间被中断
     */
    public synchronized T take() throws InterruptedException {
        while (queue.isEmpty()) {
            // 队列为空，等待新数据到来
            wait();
        }
        T item = queue.poll();
        // 移除数据后唤醒等待 put 操作的线程
        notifyAll();
        return item;
    }

    /**
     * size 方法返回当前队列中的元素个数。
     *
     * @return 队列大小
     */
    public synchronized int size() {
        return queue.size();
    }

    /**
     * isEmpty 方法用于判断队列是否为空。
     *
     * @return 如果队列为空则返回 true，否则返回 false
     */
    public synchronized boolean isEmpty() {
        return queue.isEmpty();
    }
}